#include"definicje.h"
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netdb.h>
#include<pthread.h>
#include<unistd.h>
#include"protokol.h"
#include"komunikator.h"
#include"katalogi.h"
#include"kompresja.h"
#include<openssl/rsa.h>
#include<openssl/pem.h>
#include"przeksztalcenia2.h"

#define PORT "9999"
#define PORTIPv6 "10000"

struct daneWatku
{
   struct komunikator *komunikator;
};
struct daneWatkuIPv6
{
   struct komunikatorIPv6 *komunikator;
};

const unsigned char * const gg="adc0f13a0ce06b253c26b21be3ba47f6dc65238c6fdca4da2b0c89a995af87c0481c2e6adb02474114bef96d0aa229058b7ec91940c365c04a00e409dcd2469b";
const unsigned char * const pp="ea8434f51293b3c2cd231d5c4e61116836711dca76c0bc57cfed21977746712844033377961e2fe83e6ab265f4ede4b9d158a1c32534c8ba40e65936130589f5";

mpz_t G;
mpz_t P;



int wyslijPZ(struct komunikator *k, uint8_t operacja, uint32_t ktory, uint32_t ktoryTam, uint8_t * klucz, bool szyfrowane)
{
   struct pakietACK *ack;
   int wynik;

   ack=(struct pakietACK *)malloc(rozmiarACK);
   /* no i gdzies free */
   if(ack==NULL)
   {
      fprintf(stderr,"Nie można zaalokować pamięci\n");
      return -1;
   }
   ack->naglowek.rozmiar=htons((uint16_t)4u);
   ack->naglowek.operacja=operacja;
   ack->naglowek.opcje=0u;
   ack->naglowek.ktory=htonl((uint32_t)ktory);
   ack->ktory=htonl((uint32_t)ktoryTam);
   wynik=wyslijKomunikat(k,NULL,(int8_t *)ack, klucz, szyfrowane);
   if(wynik==-1)
   {
      return -1;
   }
   return 0;
}
int wyslijPZIPv6(struct komunikatorIPv6 *k, uint8_t operacja, uint32_t ktory, uint32_t ktoryTam, uint8_t * klucz, bool szyfrowane)
{
   struct pakietACK *ack;
   int wynik;

   ack=(struct pakietACK *)malloc(rozmiarACK);
   /* no i gdzies free */
   if(ack==NULL)
   {
      fprintf(stderr,"Nie można zaalokować pamięci\n");
      return -1;
   }
   ack->naglowek.rozmiar=htons((uint16_t)4u);
   ack->naglowek.operacja=operacja;
   ack->naglowek.opcje=0u;
   ack->naglowek.ktory=htonl((uint32_t)ktory);
   ack->ktory=htonl((uint32_t)ktoryTam);
   wynik=wyslijKomunikatIPv6(k,NULL,(int8_t *)ack, klucz, szyfrowane);
   if(wynik==-1)
   {
      return -1;
   }
   return 0;
}

void *watek(void *d)
{
   /* Lista rzeczy które należy dodać:
    * 1. Powtórna próba odebrania w wypadku odebrania
    * błędnego pakietu (także w kliencie)
    * 2. Wysłanie wskaźnika pustego na socket oznacza zakończenie
    * wątku i prośbę o usunięcie gniazda po tamtej stronie
    * 3. Dodać timeout na sockety i obsługę w kodzie
    */
   uint32_t ktory=0;
   uint32_t ktoryTam=0;
   int16_t rozmiar=100;
   int8_t *bufor;
   mpz_t klucz_oryginalny;
   mpz_t klucz_aktualny;
   struct sockaddr_storage *adres;
   struct naglowek *nag;
   struct pakietACK *ack;
   struct pakietSET *set;
   struct pakietCERT *cert;
   struct pakietKEY *key;
   int8_t *dane;
   int8_t *aktualne;
   struct daneWatku *dw=(struct daneWatku *)d;
   struct elementListy *element;
   extern struct elementListy *katalogi;

   int8_t *napis;
   FILE* plik;
   FILE* plik_temp;
   FILE* cert_pub;
   FILE* cert_pub2;
   long dlugoscPliku;
   size_t zapisane;
   int wynik;
   uint8_t certyfikat[500];
   uint8_t certyfikat2[500];
   uint8_t klucz[128];
   RSA *rsa_pub;
   size_t w_cert;
   int cert_pasuje;

   mpz_init(klucz_oryginalny);
   mpz_init(klucz_aktualny);

    cert_pub2=fopen("klient-public.pem","r");
    w_cert=fread(certyfikat2,sizeof(uint8_t),500,cert_pub2);

    cert_pub=fopen("server-priv.pem","r");
    rsa_pub = PEM_read_RSAPrivateKey(cert_pub,NULL,NULL,NULL);




/*
fprintf(stderr,"czekam na hello\n");

   wynik=przyjmijKomunikat(dw->komunikator,&adres,&bufor);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktoryTam;

    set=(struct pakietSET *)bufor;

   if (set->naglowek.operacja==OP_HELLO )
   {

       fprintf(stderr,"hello\n");
       wynik=wyslijPZ(dw->komunikator,OP_ACK,ktory,ktoryTam-1);
       ++ktory;

   }
*/

#ifdef DEBUG
   fprintf(stderr,"Watek czeka na komunikat\n");
#endif
   wynik=przyjmijKomunikat(dw->komunikator,&adres,&bufor, 0, false);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktoryTam;

#ifdef DEBUG
   fprintf(stderr,"Watek otrzymal komunikat\n");
#endif
   cert=(struct pakietCERT *)bufor;

   fprintf(stderr,"operacja=%u\n",cert->naglowek.operacja);

   if(cert->naglowek.operacja==OP_CERT && cert->naglowek.rozmiar==htons((uint16_t)500u))
   {
#ifdef DEBUG
   fprintf(stderr,"Odebrałem certyfikat\n");
   fprintf(stderr,cert->certyfikat);
   fprintf(stderr,"\nDługość certyfikatu=%u\n",strlen(cert->certyfikat));
#endif

    cert_pasuje=memcmp(certyfikat2,cert->certyfikat,strlen(cert->certyfikat));

    /* W cert->certyfikat jest certyfikat. Obetnij gdy trafisz na zero. */
      //certyfikat=(uint8_t*)malloc(strlen(cert->certyfikat)+sizeof(uint8_t));
      memcpy(certyfikat,cert->certyfikat,sizeof(uint8_t[500]));
      free(bufor);
   }
   else
   {
      free(bufor);
      fprintf(stderr,"Błędna operacja. Oczekiwano operacji CERT.\n");
      pthread_exit(NULL);
   }
   if(cert_pasuje==0)
   {

#ifdef DEBUG
	   fprintf(stderr,"Watek wysyla potwierdzenie\n");
	   //fprintf(stderr,"ktory=%u,ktoryTam=%u\n");
#endif
	   wynik=wyslijPZ(dw->komunikator,OP_ACK,ktory,ktoryTam-1, 0, false);
	   if(wynik==-1)
	   {
	      pthread_exit(NULL);
	   }
	   ++ktory;
   }

#ifdef DEBUG
   fprintf(stderr,"Watek czeka na komunikat\n");
#endif
   wynik=przyjmijKomunikat(dw->komunikator,&adres,&bufor, 0, false);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktoryTam;

#ifdef DEBUG
   fprintf(stderr,"Watek otrzymal komunikat\n");
#endif
   key=(struct pakietKEY *)bufor;

   if(key->naglowek.operacja==OP_KEY && key->naglowek.rozmiar==htons((uint16_t)128u))
   {
#ifdef DEBUG
   fprintf(stderr,"Odebrałem klucz\n");
#endif

   /* W key->klucz jest klucz.*/
    int bufSize=RSA_private_decrypt(128, key->klucz, klucz,rsa_pub,RSA_PKCS1_PADDING);
      //memcpy(klucz,key->klucz,sizeof(uint8_t[64]));
       free(bufor);
   }
   else
   {
      free(bufor);
      fprintf(stderr,"Błędna operacja. Oczekiwano operacji KEY.\n");
      pthread_exit(NULL);
   }

#ifdef DEBUG
   fprintf(stderr,"Watek wysyla potwierdzenie\n");
   //fprintf(stderr,"ktory=%u,ktoryTam=%u\n");
#endif
   wynik=wyslijPZ(dw->komunikator,OP_ACK,ktory,ktoryTam-1, 0, false);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktory;

#ifdef DEBUG
   fprintf(stderr,"Watek czeka na komunikat\n");
#endif
   wynik=przyjmijKomunikat(dw->komunikator,&adres,&bufor, klucz, true);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktoryTam;

#ifdef DEBUG
   fprintf(stderr,"Watek otrzymal komunikat\n");
#endif
   set=(struct pakietSET *)bufor;

   if(set->naglowek.operacja==OP_SET && set->naglowek.rozmiar==htons((uint16_t)2u))
   {
#ifdef DEBUG
   fprintf(stderr,"Ustawiam rozmiar na %hu\n",ntohs(set->rozmiar));
#endif
      rozmiar=ntohs(set->rozmiar);
      free(bufor);
   }

   else
   {
      free(bufor);
      fprintf(stderr,"Błędna operacja. Oczekiwano operacji SET.\n");
      pthread_exit(NULL);
   }
#ifdef DEBUG
   fprintf(stderr,"Watek wysyla potwierdzenie\n");
   //fprintf(stderr,"ktory=%u,ktoryTam=%u\n");
#endif
   wynik=wyslijPZ(dw->komunikator,OP_ACK,ktory,ktoryTam-1, klucz, true);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktory;



   wynik=przyjmijKomunikat(dw->komunikator,&adres,&bufor, klucz, true);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktoryTam;
   nag=(struct naglowek *)bufor;
   dane=bufor+rozmiarNaglowka;

   if(nag->operacja==OP_LIST && nag->rozmiar==ntohs((uint16_t)0u))
   {
      free(bufor);
      bufor=(int8_t *)malloc(rozmiarACK+dlugoscListyKatalogow());
#ifdef DEBUG
      fprintf(stderr,"dlugoscListyKatalogow=%u",dlugoscListyKatalogow());
#endif
      ack=(struct pakietACK *)bufor;
      dane=bufor+rozmiarACK;
      aktualne=dane;
      for(element=katalogi;element!=NULL;element=element->nastepny)
      {
	 strcpy(aktualne,element->katalog.d_name);
	 aktualne+=strlen(element->katalog.d_name);
	 *aktualne='\n';
	 ++aktualne;
      }

      ack->naglowek.rozmiar=htons((int16_t)(aktualne-dane)+sizeof(uint32_t));
      ack->naglowek.operacja=OP_ACK;
      ack->naglowek.opcje=0u;
      ack->naglowek.ktory=htonl((uint32_t)ktory);
      ack->ktory=htonl((uint32_t)ktoryTam-1);
#ifdef DEBUG
   fprintf(stderr,"rozmiar=%u\n",ack->naglowek.rozmiar);
#endif
      wynik=wyslijKomunikat(dw->komunikator,NULL,bufor, klucz, true);
      if(wynik==-1)
      {
	 pthread_exit(NULL);
      }
      ++ktory;
   }
   else
   {
      free(bufor);
      fprintf(stderr,"Błędna operacja. Oczekiwano operacji LIST.\n");
      pthread_exit(NULL);
   }

   wynik=przyjmijKomunikat(dw->komunikator,&adres,&bufor, klucz, true);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktoryTam;
   nag=(struct naglowek *)bufor;
   dane=bufor+rozmiarNaglowka;

   if(nag->operacja==OP_GET)
   {
      napis=(int8_t *)malloc(ntohs(nag->rozmiar)+1);
      memcpy(napis,dane,ntohs(nag->rozmiar));
      napis[ntohs(nag->rozmiar)]='\0';
#ifdef DEBUG
   fprintf(stderr,"Otwieram plik\n");
#endif
      plik_temp=fopen(napis,"rb");
      if(plik_temp==NULL)
      {
	 perror("fopen");
	 pthread_exit(NULL);
      }


      plik=tmpfile();
    //plik=fopen("test.tct.txt","w+b");
      if(plik==NULL)
      {
	 perror("fopen");
	 pthread_exit(NULL);
      }


      wynik = def(plik_temp, plik, Z_DEFAULT_COMPRESSION);
        if (wynik != Z_OK)
          {
              fprintf(stderr,"blad kompresji\n");
              fclose(plik_temp);
              pthread_exit(NULL);
          }
          fflush(plik);
    rewind(plik);
      free(bufor);
      fclose(plik_temp);

#ifdef DEBUG
   fprintf(stderr,"Szukam końca pliku\n");
#endif
      wynik=fseek(plik,0L,SEEK_END);
      if(wynik==-1)
      {
	 fclose(plik);
	 perror("fseek");
	 pthread_exit(NULL);
      }
#ifdef DEBUG
   fprintf(stderr,"Przechodzę do końca pliku\n");
#endif
      dlugoscPliku=ftell(plik);
      if(dlugoscPliku==-1L)
      {
	 fclose(plik);
	 perror("ftell");
	 pthread_exit(NULL);
      }
#ifdef DEBUG
   fprintf(stderr,"Wracam na początek pliku\n");
#endif
      wynik=fseek(plik,0L,SEEK_SET);
      if(wynik==-1)
      {
	 fclose(plik);
	 perror("fseek");
	 pthread_exit(NULL);
      }

      bufor=(int8_t *)malloc(rozmiarACK+sizeof(uint32_t));
      if(bufor==NULL)
      {
	 fclose(plik);
	 fprintf(stderr,"Nie można zaalokować pamięci\n");
	 pthread_exit(NULL);

      }
      dane=bufor+rozmiarACK;
      ack=(struct pakietACK *)bufor;

      ack->naglowek.rozmiar=htons(2*sizeof(uint32_t));
      ack->naglowek.operacja=OP_ACK;
      ack->naglowek.opcje=(int8_t)0u;
      ack->naglowek.ktory=htonl(ktory);
      ack->ktory=htonl(ktoryTam-1);
      {
	 uint32_t *l=(uint32_t *)dane;
	 *l=htonl(dlugoscPliku%rozmiar?dlugoscPliku/rozmiar+1:dlugoscPliku/rozmiar);
#ifdef DEBUG
   fprintf(stderr,"WYSYŁAM %u pakietów\n",ntohl(*l));
#endif
      }

      wynik=wyslijKomunikat(dw->komunikator,NULL,bufor, klucz, true);
      if(wynik==-1)
      {
	 fclose(plik);
	 pthread_exit(NULL);
      }
      ++ktory;

#ifdef DEBUG
   fprintf(stderr,"Za chwilę wejdę do pętli wysyłającej plik\n");
#endif
      while(!feof(plik))
      {
#ifdef DEBUG
	 fprintf(stderr,"iteracja...\n");
#endif
	 bufor=(int8_t *)malloc(rozmiarNaglowka+rozmiar);
	 nag=(struct naglowek *)bufor;
	 dane=bufor+rozmiarNaglowka;

	 nag->rozmiar=htons(rozmiar);
	 nag->operacja=OP_DAT;
	 nag->opcje=(int8_t)0u;
	 nag->ktory=htonl(ktory);

	 zapisane=fread(dane,sizeof(int8_t),rozmiar,plik);

	 mpz_import(klucz_oryginalny,64,1,sizeof(uint8_t),1,0,klucz);
    	 mpz_set(klucz_aktualny,klucz_oryginalny);
    	 gmp_fprintf(stderr,"#################################KLUCZ=%Qx\n",klucz_aktualny);
	 for(int i=0;i<zapisane;i++)
	 {
        dane[i]=szydefruj2(dane[i],klucz_aktualny);
	 }
	 if(zapisane==0)
	 {
	    break;
	 }

#ifdef DEBUG
	 fprintf(stderr,"Wczytano %u bajtów z pliku\n",zapisane);
#endif

	 nag->rozmiar=htons(zapisane);

#ifdef DEBUG
   fprintf(stderr,"Zaraz wyslijKomunikat()\n");
#endif
	 wynik=wyslijKomunikat(dw->komunikator,NULL,bufor, klucz, true);
	 if(wynik==-1)
	 {
	    fclose(plik);
	    pthread_exit(NULL);
	 }
	 ++ktory;
#ifdef DEBUG
   fprintf(stderr,"Koniec wysylanie wyslijKomunikat()\n");
#endif

#ifdef DEBUG
   fprintf(stderr,"Wysłałem pakiet, czekam na potwierdzenie\n");
#endif
	 wynik=przyjmijKomunikat(dw->komunikator,&adres,&bufor, klucz, true);
	 if(wynik==-1)
	 {
	    fclose(plik);
	    pthread_exit(NULL);
	 }
#ifdef DEBUG
   fprintf(stderr,"Otrzymałem potwierdzenie\n");
#endif
	 ++ktoryTam;
	 nag=(struct naglowek *)bufor;
	 dane=bufor+rozmiarNaglowka;

	 if(nag->operacja!=OP_ACK)
	 {
	    /*ERROR*/
	    /*Jeżeli nie dostałem potwierdzenia*/
	 }
      }

#ifdef DEBUG
      fprintf(stderr,"OK! Plik został wysłany\n");
#endif
      fclose(plik);
   }
   else
   {
      free(bufor);
      fprintf(stderr,"Błędna operacja. Oczekiwano operacji GET.\n");
      pthread_exit(NULL);
   }

#ifdef DEBUG
   fprintf(stderr,"Czekam za zakończenie\n");
#endif
   wynik=przyjmijKomunikat(dw->komunikator,&adres,&bufor, klucz, true);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktoryTam;
   nag=(struct naglowek *)bufor;
   dane=bufor+rozmiarNaglowka;


   if(nag->operacja!=OP_QUIT)
   {
      free(bufor);
      fprintf(stderr,"Błędna operacja. Oczekiwano operacji QUIT.\n");
      pthread_exit(NULL);
   }
   free(bufor);

#ifdef DEBUG
   fprintf(stderr,"Wysyłam potwierdzenie zakończenia\n");
#endif
   wynik=wyslijPZ(dw->komunikator,OP_ACK,ktory,ktoryTam-1, klucz, true);
   close(dw->komunikator->gniazdo);
   free(dw->komunikator);
   free(d);

#ifdef DEBUG
   fprintf(stderr,"Koniec\n");
   fflush(stderr);
#endif
   pthread_exit(NULL);
}

void *watekIPv6(void *d)
{
   /* Lista rzeczy które należy dodać:
    * 1. Powtórna próba odebrania w wypadku odebrania
    * błędnego pakietu (także w kliencie)
    * 2. Wysłanie wskaźnika pustego na socket oznacza zakończenie
    * wątku i prośbę o usunięcie gniazda po tamtej stronie
    * 3. Dodać timeout na sockety i obsługę w kodzie
    */
   uint32_t ktory=0;
   uint32_t ktoryTam=0;
   int16_t rozmiar=100;
   int8_t *bufor;
   mpz_t klucz_oryginalny;
   mpz_t klucz_aktualny;
   struct sockaddr_storage *adres;
   struct naglowek *nag;
   struct pakietACK *ack;
   struct pakietSET *set;
   struct pakietCERT *cert;
   struct pakietKEY *key;
   int8_t *dane;
   int8_t *aktualne;
   struct daneWatkuIPv6 *dw=(struct daneWatkuIPv6 *)d;
   struct elementListy *element;
   extern struct elementListy *katalogi;

   int8_t *napis;
   FILE* plik;
   FILE* plik_temp;
   FILE* cert_pub;
   FILE* cert_pub2;
   long dlugoscPliku;
   size_t zapisane;
   int wynik;
   uint8_t certyfikat[500];
   uint8_t certyfikat2[500];
   uint8_t klucz[128];
   RSA *rsa_pub;
   size_t w_cert;
   int cert_pasuje;

   mpz_init(klucz_oryginalny);
   mpz_init(klucz_aktualny);

    cert_pub2=fopen("klient-public.pem","r");
    w_cert=fread(certyfikat2,sizeof(uint8_t),500,cert_pub2);

    cert_pub=fopen("klient-public.pem","r");
    rsa_pub = PEM_read_RSA_PUBKEY(cert_pub,NULL,NULL,NULL);




/*
fprintf(stderr,"czekam na hello\n");

   wynik=przyjmijKomunikat(dw->komunikator,&adres,&bufor);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktoryTam;

    set=(struct pakietSET *)bufor;

   if (set->naglowek.operacja==OP_HELLO )
   {

       fprintf(stderr,"hello\n");
       wynik=wyslijPZ(dw->komunikator,OP_ACK,ktory,ktoryTam-1);
       ++ktory;

   }
*/

#ifdef DEBUG
   fprintf(stderr,"Watek czeka na komunikat\n");
#endif
   wynik=przyjmijKomunikatIPv6(dw->komunikator,&adres,&bufor, 0, false);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktoryTam;

#ifdef DEBUG
   fprintf(stderr,"Watek otrzymal komunikat\n");
#endif
   cert=(struct pakietCERT *)bufor;

   fprintf(stderr,"operacja=%u\n",cert->naglowek.operacja);

   if(cert->naglowek.operacja==OP_CERT && cert->naglowek.rozmiar==htons((uint16_t)500u))
   {
#ifdef DEBUG
   fprintf(stderr,"Odebrałem certyfikat\n");
   fprintf(stderr,cert->certyfikat);
   fprintf(stderr,"\nDługość certyfikatu=%u\n",strlen(cert->certyfikat));
#endif

    cert_pasuje=memcmp(certyfikat2,cert->certyfikat,strlen(cert->certyfikat));

    /* W cert->certyfikat jest certyfikat. Obetnij gdy trafisz na zero. */
      //certyfikat=(uint8_t*)malloc(strlen(cert->certyfikat)+sizeof(uint8_t));
      memcpy(certyfikat,cert->certyfikat,sizeof(uint8_t[500]));
      free(bufor);
   }
   else
   {
      free(bufor);
      fprintf(stderr,"Błędna operacja. Oczekiwano operacji CERT.\n");
      pthread_exit(NULL);
   }
   if(cert_pasuje==0)
   {

#ifdef DEBUG
	   fprintf(stderr,"Watek wysyla potwierdzenie\n");
	   //fprintf(stderr,"ktory=%u,ktoryTam=%u\n");
#endif
	   wynik=wyslijPZIPv6(dw->komunikator,OP_ACK,ktory,ktoryTam-1, 0, false);
	   if(wynik==-1)
	   {
	      pthread_exit(NULL);
	   }
	   ++ktory;
   }

#ifdef DEBUG
   fprintf(stderr,"Watek czeka na komunikat\n");
#endif
   wynik=przyjmijKomunikatIPv6(dw->komunikator,&adres,&bufor, 0, false);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktoryTam;

#ifdef DEBUG
   fprintf(stderr,"Watek otrzymal komunikat\n");
#endif
   key=(struct pakietKEY *)bufor;

   if(key->naglowek.operacja==OP_KEY && key->naglowek.rozmiar==htons((uint16_t)128u))
   {
#ifdef DEBUG
   fprintf(stderr,"Odebrałem klucz\n");
#endif

   /* W key->klucz jest klucz.*/
    int bufSize=RSA_public_decrypt(128, key->klucz, klucz,rsa_pub,RSA_PKCS1_PADDING);
      //memcpy(klucz,key->klucz,sizeof(uint8_t[64]));
       free(bufor);
   }
   else
   {
      free(bufor);
      fprintf(stderr,"Błędna operacja. Oczekiwano operacji KEY.\n");
      pthread_exit(NULL);
   }

#ifdef DEBUG
   fprintf(stderr,"Watek wysyla potwierdzenie\n");
   //fprintf(stderr,"ktory=%u,ktoryTam=%u\n");
#endif
   wynik=wyslijPZIPv6(dw->komunikator,OP_ACK,ktory,ktoryTam-1, 0, false);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktory;

#ifdef DEBUG
   fprintf(stderr,"Watek czeka na komunikat\n");
#endif
   wynik=przyjmijKomunikatIPv6(dw->komunikator,&adres,&bufor, klucz, true);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktoryTam;

#ifdef DEBUG
   fprintf(stderr,"Watek otrzymal komunikat\n");
#endif
   set=(struct pakietSET *)bufor;

   if(set->naglowek.operacja==OP_SET && set->naglowek.rozmiar==htons((uint16_t)2u))
   {
#ifdef DEBUG
   fprintf(stderr,"Ustawiam rozmiar na %hu\n",ntohs(set->rozmiar));
#endif
      rozmiar=ntohs(set->rozmiar);
      free(bufor);
   }

   else
   {
      free(bufor);
      fprintf(stderr,"Błędna operacja. Oczekiwano operacji SET.\n");
      pthread_exit(NULL);
   }
#ifdef DEBUG
   fprintf(stderr,"Watek wysyla potwierdzenie\n");
   //fprintf(stderr,"ktory=%u,ktoryTam=%u\n");
#endif
   wynik=wyslijPZIPv6(dw->komunikator,OP_ACK,ktory,ktoryTam-1, klucz, true);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktory;



   wynik=przyjmijKomunikatIPv6(dw->komunikator,&adres,&bufor, klucz, true);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktoryTam;
   nag=(struct naglowek *)bufor;
   dane=bufor+rozmiarNaglowka;

   if(nag->operacja==OP_LIST && nag->rozmiar==ntohs((uint16_t)0u))
   {
      free(bufor);
      bufor=(int8_t *)malloc(rozmiarACK+dlugoscListyKatalogow());
#ifdef DEBUG
      fprintf(stderr,"dlugoscListyKatalogow=%u",dlugoscListyKatalogow());
#endif
      ack=(struct pakietACK *)bufor;
      dane=bufor+rozmiarACK;
      aktualne=dane;
      for(element=katalogi;element!=NULL;element=element->nastepny)
      {
	 strcpy(aktualne,element->katalog.d_name);
	 aktualne+=strlen(element->katalog.d_name);
	 *aktualne='\n';
	 ++aktualne;
      }

      ack->naglowek.rozmiar=htons((int16_t)(aktualne-dane)+sizeof(uint32_t));
      ack->naglowek.operacja=OP_ACK;
      ack->naglowek.opcje=0u;
      ack->naglowek.ktory=htonl((uint32_t)ktory);
      ack->ktory=htonl((uint32_t)ktoryTam-1);
#ifdef DEBUG
   fprintf(stderr,"rozmiar=%u\n",ack->naglowek.rozmiar);
#endif
      wynik=wyslijKomunikatIPv6(dw->komunikator,NULL,bufor, klucz, true);
      if(wynik==-1)
      {
	 pthread_exit(NULL);
      }
      ++ktory;
   }
   else
   {
      free(bufor);
      fprintf(stderr,"Błędna operacja. Oczekiwano operacji LIST.\n");
      pthread_exit(NULL);
   }

   wynik=przyjmijKomunikatIPv6(dw->komunikator,&adres,&bufor, klucz, true);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktoryTam;
   nag=(struct naglowek *)bufor;
   dane=bufor+rozmiarNaglowka;

   if(nag->operacja==OP_GET)
   {
      napis=(int8_t *)malloc(ntohs(nag->rozmiar)+1);
      memcpy(napis,dane,ntohs(nag->rozmiar));
      napis[ntohs(nag->rozmiar)]='\0';
#ifdef DEBUG
   fprintf(stderr,"Otwieram plik\n");
#endif
      plik_temp=fopen(napis,"rb");
      if(plik_temp==NULL)
      {
	 perror("fopen");
	 pthread_exit(NULL);
      }


      plik=tmpfile();
    //plik=fopen("test.tct.txt","w+b");
      if(plik==NULL)
      {
	 perror("fopen");
	 pthread_exit(NULL);
      }


      wynik = def(plik_temp, plik, Z_DEFAULT_COMPRESSION);
        if (wynik != Z_OK)
          {
              fprintf(stderr,"blad kompresji\n");
              fclose(plik_temp);
              pthread_exit(NULL);
          }
          fflush(plik);
    rewind(plik);
      free(bufor);
      fclose(plik_temp);

#ifdef DEBUG
   fprintf(stderr,"Szukam końca pliku\n");
#endif
      wynik=fseek(plik,0L,SEEK_END);
      if(wynik==-1)
      {
	 fclose(plik);
	 perror("fseek");
	 pthread_exit(NULL);
      }
#ifdef DEBUG
   fprintf(stderr,"Przechodzę do końca pliku\n");
#endif
      dlugoscPliku=ftell(plik);
      if(dlugoscPliku==-1L)
      {
	 fclose(plik);
	 perror("ftell");
	 pthread_exit(NULL);
      }
#ifdef DEBUG
   fprintf(stderr,"Wracam na początek pliku\n");
#endif
      wynik=fseek(plik,0L,SEEK_SET);
      if(wynik==-1)
      {
	 fclose(plik);
	 perror("fseek");
	 pthread_exit(NULL);
      }

      bufor=(int8_t *)malloc(rozmiarACK+sizeof(uint32_t));
      if(bufor==NULL)
      {
	 fclose(plik);
	 fprintf(stderr,"Nie można zaalokować pamięci\n");
	 pthread_exit(NULL);

      }
      dane=bufor+rozmiarACK;
      ack=(struct pakietACK *)bufor;

      ack->naglowek.rozmiar=htons(2*sizeof(uint32_t));
      ack->naglowek.operacja=OP_ACK;
      ack->naglowek.opcje=(int8_t)0u;
      ack->naglowek.ktory=htonl(ktory);
      ack->ktory=htonl(ktoryTam-1);
      {
	 uint32_t *l=(uint32_t *)dane;
	 *l=htonl(dlugoscPliku%rozmiar?dlugoscPliku/rozmiar+1:dlugoscPliku/rozmiar);
#ifdef DEBUG
   fprintf(stderr,"WYSYŁAM %u pakietów\n",ntohl(*l));
#endif
      }

      wynik=wyslijKomunikatIPv6(dw->komunikator,NULL,bufor, klucz, true);
      if(wynik==-1)
      {
	 fclose(plik);
	 pthread_exit(NULL);
      }
      ++ktory;

#ifdef DEBUG
   fprintf(stderr,"Za chwilę wejdę do pętli wysyłającej plik\n");
#endif
      while(!feof(plik))
      {
#ifdef DEBUG
	 fprintf(stderr,"iteracja...\n");
#endif
	 bufor=(int8_t *)malloc(rozmiarNaglowka+rozmiar);
	 nag=(struct naglowek *)bufor;
	 dane=bufor+rozmiarNaglowka;

	 nag->rozmiar=htons(rozmiar);
	 nag->operacja=OP_DAT;
	 nag->opcje=(int8_t)0u;
	 nag->ktory=htonl(ktory);

	 zapisane=fread(dane,sizeof(int8_t),rozmiar,plik);

	 mpz_import(klucz_oryginalny,64,1,sizeof(uint8_t),1,0,klucz);
    	 mpz_set(klucz_aktualny,klucz_oryginalny);
    	 gmp_fprintf(stderr,"#################################KLUCZ=%Qx\n",klucz_aktualny);
	 for(int i=0;i<zapisane;i++)
	 {
        dane[i]=szydefruj2(dane[i],klucz_aktualny);
	 }
	 if(zapisane==0)
	 {
	    break;
	 }

#ifdef DEBUG
	 fprintf(stderr,"Wczytano %u bajtów z pliku\n",zapisane);
#endif

	 nag->rozmiar=htons(zapisane);

#ifdef DEBUG
   fprintf(stderr,"Zaraz wyslijKomunikat()\n");
#endif
	 wynik=wyslijKomunikatIPv6(dw->komunikator,NULL,bufor, klucz, true);
	 if(wynik==-1)
	 {
	    fclose(plik);
	    pthread_exit(NULL);
	 }
	 ++ktory;
#ifdef DEBUG
   fprintf(stderr,"Koniec wysylanie wyslijKomunikat()\n");
#endif

#ifdef DEBUG
   fprintf(stderr,"Wysłałem pakiet, czekam na potwierdzenie\n");
#endif
	 wynik=przyjmijKomunikatIPv6(dw->komunikator,&adres,&bufor, klucz, true);
	 if(wynik==-1)
	 {
	    fclose(plik);
	    pthread_exit(NULL);
	 }
#ifdef DEBUG
   fprintf(stderr,"Otrzymałem potwierdzenie\n");
#endif
	 ++ktoryTam;
	 nag=(struct naglowek *)bufor;
	 dane=bufor+rozmiarNaglowka;

	 if(nag->operacja!=OP_ACK)
	 {
	    /*ERROR*/
	    /*Jeżeli nie dostałem potwierdzenia*/
	 }
      }

#ifdef DEBUG
      fprintf(stderr,"OK! Plik został wysłany\n");
#endif
      fclose(plik);
   }
   else
   {
      free(bufor);
      fprintf(stderr,"Błędna operacja. Oczekiwano operacji GET.\n");
      pthread_exit(NULL);
   }

#ifdef DEBUG
   fprintf(stderr,"Czekam za zakończenie\n");
#endif
   wynik=przyjmijKomunikatIPv6(dw->komunikator,&adres,&bufor, klucz, true);
   if(wynik==-1)
   {
      pthread_exit(NULL);
   }
   ++ktoryTam;
   nag=(struct naglowek *)bufor;
   dane=bufor+rozmiarNaglowka;


   if(nag->operacja!=OP_QUIT)
   {
      free(bufor);
      fprintf(stderr,"Błędna operacja. Oczekiwano operacji QUIT.\n");
      pthread_exit(NULL);
   }
   free(bufor);

#ifdef DEBUG
   fprintf(stderr,"Wysyłam potwierdzenie zakończenia\n");
#endif
   wynik=wyslijPZIPv6(dw->komunikator,OP_ACK,ktory,ktoryTam-1, klucz, true);
   close(dw->komunikator->gniazdo);
   free(dw->komunikator);
   free(d);

#ifdef DEBUG
   fprintf(stderr,"Koniec\n");
   fflush(stderr);
#endif
   pthread_exit(NULL);
}

int stworzGniazdoNasluchujaceIPv6(int *gniazdo)
{
   unsigned int i;
   int wynik;
   struct addrinfo *adresy, *wskaznik;
   struct addrinfo wskazowki;

   memset(&wskazowki, 0, sizeof(struct addrinfo));
   //wskazowki.ai_family = AF_UNSPEC;
   wskazowki.ai_family = AF_INET6;
   wskazowki.ai_socktype = SOCK_DGRAM;
   wskazowki.ai_flags = AI_PASSIVE;

   wynik=getaddrinfo(NULL,PORTIPv6,&wskazowki,&adresy);
   if(wynik!=0)
   {
      fprintf(stderr, "getaddrinfo: %s\n",gai_strerror(wynik));
      return -1;
   }
   for(wskaznik = adresy; wskaznik != NULL; wskaznik=wskaznik->ai_next)
   {
      *gniazdo=socket(
	    wskaznik->ai_family,
	    wskaznik->ai_socktype,
	    wskaznik->ai_protocol);
      if(*gniazdo==-1)
      {
	 perror("socket");
	 continue;
      }
      wynik=bind(*gniazdo,wskaznik->ai_addr,wskaznik->ai_addrlen);
      if(wynik==-1)
      {
	 close(*gniazdo);
	 perror("bind");
	 continue;
      }
      freeaddrinfo(adresy);
      return 0;
   }
   freeaddrinfo(adresy);
   return -1;
}

int stworzGniazdoNasluchujace(int *gniazdo)
{
   unsigned int i;
   int wynik;
   struct addrinfo *adresy, *wskaznik;
   struct addrinfo wskazowki;

   memset(&wskazowki, 0, sizeof(struct addrinfo));
   //wskazowki.ai_family = AF_UNSPEC;
   wskazowki.ai_family = AF_INET;
   wskazowki.ai_socktype = SOCK_DGRAM;
   wskazowki.ai_flags = AI_PASSIVE;

   wynik=getaddrinfo(NULL,PORT,&wskazowki,&adresy);
   if(wynik!=0)
   {
      fprintf(stderr, "getaddrinfo: %s\n",gai_strerror(wynik));
      return -1;
   }
   for(wskaznik = adresy; wskaznik != NULL; wskaznik=wskaznik->ai_next)
   {
      *gniazdo=socket(
	    wskaznik->ai_family,
	    wskaznik->ai_socktype,
	    wskaznik->ai_protocol);
      if(*gniazdo==-1)
      {
	 perror("socket");
	 continue;
      }
      wynik=bind(*gniazdo,wskaznik->ai_addr,wskaznik->ai_addrlen);
      if(wynik==-1)
      {
	 close(*gniazdo);
	 perror("bind");
	 continue;
      }
      freeaddrinfo(adresy);
      return 0;
   }
   freeaddrinfo(adresy);
   return -1;
}

int inicjalizujCentraleIPv6(int gniazdo)
{
   struct komunikatorIPv6 *nowy;
   int wynik;

   nowy=(struct komunikatorIPv6 *)malloc(sizeof(struct komunikatorIPv6));
   if(nowy==NULL)
   {
      fprintf(stderr,"Nie udało się zaalokować pamięci\n");
      return -1;
   }
   nowy->adres=NULL;
   nowy->gniazdo=gniazdo;
   wynik=dodajKomunikatorIPv6(nowy);
   if(wynik==-1)
   {
      return -1;
   }
   return 0;
}

int inicjalizujCentrale(int gniazdo)
{
   struct komunikator *nowy;
   int wynik;

   nowy=(struct komunikator *)malloc(sizeof(struct komunikator));
   if(nowy==NULL)
   {
      fprintf(stderr,"Nie udało się zaalokować pamięci\n");
      return -1;
   }
   nowy->adres=NULL;
   nowy->gniazdo=gniazdo;
   wynik=dodajKomunikator(nowy);
   if(wynik==-1)
   {
      return -1;
   }
   return 0;
}

int stworzWatek(struct sockaddr_storage *adres, struct komunikator **kom)
{
   int wynik;
   int gniazda[2];
   struct daneWatku *dane;
   struct komunikator *wkom;
   struct sockaddr_storage *a;
   pthread_t w;

   *kom=(struct komunikator *)malloc(sizeof(struct komunikator));
   if(*kom==NULL)
   {
      fprintf(stderr,"Nie udało się zaalokować  pamięci\n");
      return -1;
   }
   /* należy dorobić free gdzieś w kodzie */
   wkom=(struct komunikator *)malloc(sizeof(struct komunikator));
   if(wkom==NULL)
   {
      free(*kom);
      fprintf(stderr,"Nie udało się zaalokować  pamięci\n");
      return -1;
   }
   /* należy dorobić free gdzieś w kodzie */
   a=(struct sockaddr_storage *)malloc(sizeof(struct sockaddr_storage));
   if(a==NULL)
   {
      free(*kom);
      free(wkom);
      fprintf(stderr,"Nie udało się zaalokować  pamięci\n");
      return -1;
   }
   /* należy dorobić free gdzieś w kodzie */
   memcpy(a,adres,sizeof(struct sockaddr_storage));
   wynik=socketpair(AF_UNIX,SOCK_DGRAM,0,gniazda);
   if(wynik==-1)
   {
      free(*kom);
      free(wkom);
      free(a);
      perror("socketpair");
      return -1;
   }

   dane=malloc(sizeof(struct daneWatku));
   if(dane==NULL)
   {
      free(*kom);
      free(wkom);
      free(a);
      close(gniazda[0]);
      close(gniazda[1]);
      fprintf(stderr,"Nie udało się zaalokować  pamięci\n");
      return -1;
   }
   (*kom)->adres=adres;
   (*kom)->gniazdo=gniazda[0];
   wkom->adres=a;
   wkom->gniazdo=gniazda[1];
   dane->komunikator=wkom;

   wynik=pthread_create(&w,NULL,watek,dane);
   if(wynik!=0)
   {
      free(*kom);
      free(wkom);
      free(a);
      close(gniazda[0]);
      close(gniazda[1]);
      return -1;
   }
   wynik=pthread_detach(w);
   if(wynik!=0)
   {
      free(*kom);
      free(wkom);
      free(a);
      close(gniazda[0]);
      close(gniazda[1]);
      pthread_kill(w,SIGTERM);
      return -1;
   }
   wynik=dodajKomunikator(*kom);
   if(wynik==-1)
   {
      free(*kom);
      free(wkom);
      free(a);
      close(gniazda[0]);
      close(gniazda[1]);
      pthread_kill(w,SIGTERM);
      return -1;
   }
   return 0;
}
int stworzWatekIPv6(struct sockaddr_storage *adres, struct komunikatorIPv6 **kom)
{
   int wynik;
   int gniazda[2];
   struct daneWatkuIPv6 *dane;
   struct komunikatorIPv6 *wkom;
   struct sockaddr_storage *a;
   pthread_t w;

   *kom=(struct komunikatorIPv6 *)malloc(sizeof(struct komunikatorIPv6));
   if(*kom==NULL)
   {
      fprintf(stderr,"Nie udało się zaalokować  pamięci\n");
      return -1;
   }
   /* należy dorobić free gdzieś w kodzie */
   wkom=(struct komunikatorIPv6 *)malloc(sizeof(struct komunikatorIPv6));
   if(wkom==NULL)
   {
      free(*kom);
      fprintf(stderr,"Nie udało się zaalokować  pamięci\n");
      return -1;
   }
   /* należy dorobić free gdzieś w kodzie */
   a=(struct sockaddr_storage *)malloc(sizeof(struct sockaddr_storage));
   if(a==NULL)
   {
      free(*kom);
      free(wkom);
      fprintf(stderr,"Nie udało się zaalokować  pamięci\n");
      return -1;
   }
   /* należy dorobić free gdzieś w kodzie */
   memcpy(a,adres,sizeof(struct sockaddr_storage));
   wynik=socketpair(AF_UNIX,SOCK_DGRAM,0,gniazda);
   if(wynik==-1)
   {
      free(*kom);
      free(wkom);
      free(a);
      perror("socketpair");
      return -1;
   }

   dane=malloc(sizeof(struct daneWatkuIPv6));
   if(dane==NULL)
   {
      free(*kom);
      free(wkom);
      free(a);
      close(gniazda[0]);
      close(gniazda[1]);
      fprintf(stderr,"Nie udało się zaalokować  pamięci\n");
      return -1;
   }
   (*kom)->adres=adres;
   (*kom)->gniazdo=gniazda[0];
   wkom->adres=a;
   wkom->gniazdo=gniazda[1];
   dane->komunikator=wkom;

   wynik=pthread_create(&w,NULL,watek,dane);
   if(wynik!=0)
   {
      free(*kom);
      free(wkom);
      free(a);
      close(gniazda[0]);
      close(gniazda[1]);
      return -1;
   }
   wynik=pthread_detach(w);
   if(wynik!=0)
   {
      free(*kom);
      free(wkom);
      free(a);
      close(gniazda[0]);
      close(gniazda[1]);
      pthread_kill(w,SIGTERM);
      return -1;
   }
   wynik=dodajKomunikatorIPv6(*kom);
   if(wynik==-1)
   {
      free(*kom);
      free(wkom);
      free(a);
      close(gniazda[0]);
      close(gniazda[1]);
      pthread_kill(w,SIGTERM);
      return -1;
   }
   return 0;
}

int pobierzWyslij(struct komunikator *k)
{
   int8_t *bufor;
   struct sockaddr_storage *adres;
   struct komunikator *kom;
   int wynik;

#ifdef DEBUG
   fprintf(stderr,"Wchodze do funkcji pobierzWyslij\n");
   fprintf(stderr,"Za chwile przyjme komunikat\n");
#endif
   wynik=przyjmijKomunikat(k,&adres,&bufor,0, false);
   if(wynik==-1)
   {
      return -1;
   }
#ifdef DEBUG
   fprintf(stderr,"Za chwile bede szukal komunikatora\n");
#endif
   wynik=znajdzKomunikator(adres,&kom);
   if(wynik==-1)
   {

#ifdef DEBUG
      fprintf(stderr,"Za chwile utworze watek\n");
#endif
      wynik=stworzWatek(adres,&kom);
      if(wynik==-1)
      {
	 return -1;
      }
   }
#ifdef DEBUG
   fprintf(stderr,"Za chwile wysle komunikat\n");
#endif
   wynik=wyslijKomunikat(kom,k->adres,bufor,0,false);
   if(wynik==-1)
   {
      return -1;
   }
   return 0;
}
int pobierzWyslijIPv6(struct komunikatorIPv6 *k)
{
   int8_t *bufor;
   struct sockaddr_storage *adres;
   struct komunikatorIPv6 *kom;
   int wynik;

#ifdef DEBUG
   fprintf(stderr,"Wchodze do funkcji pobierzWyslij\n");
   fprintf(stderr,"Za chwile przyjme komunikat\n");
#endif
   wynik=przyjmijKomunikatIPv6(k,&adres,&bufor,0, false);
   if(wynik==-1)
   {
      return -1;
   }
#ifdef DEBUG
   fprintf(stderr,"Za chwile bede szukal komunikatora\n");
#endif
   wynik=znajdzKomunikatorIPv6(adres,&kom);
   if(wynik==-1)
   {

#ifdef DEBUG
      fprintf(stderr,"Za chwile utworze watek\n");
#endif
      wynik=stworzWatekIPv6(adres,&kom);
      if(wynik==-1)
      {
	 return -1;
      }
   }
#ifdef DEBUG
   fprintf(stderr,"Za chwile wysle komunikat\n");
#endif
   wynik=wyslijKomunikatIPv6(kom,k->adres,bufor,0,false);
   if(wynik==-1)
   {
      return -1;
   }
   return 0;
}


int main(int argc, char *argv[])
{
   int gniazdo;
   int gniazdoIPv6;
   int wyjscie;
   unsigned int i;
   struct komunikator **k;
   struct komunikatorIPv6 **kIPv6;
   unsigned int ilosc;
   unsigned int iloscIPv6;


    piszsyslog("Serwer wystartowal",false);

    inicjalizuj();
   mpz_init(G);
   mpz_init(P);
   mpz_set_str(G,gg,16);
   mpz_set_str(P,pp,16);
   ustawG(G);
   ustawP(P);
   /*Po tym biblioteka gotowa do użycia*/


#ifdef DEBUG
   fprintf(stderr,"Wczytuję pliki w katalogu\n");
#endif
    piszsyslog("Wczytuję pliki w katalogu",false);

   wyjscie=wczytajKatalogi();
   if(wyjscie==-1)
   {
      return -1;
   }

    piszsyslog("Otwieram gniazdo nasłuchujące",false);
#ifdef DEBUG
   fprintf(stderr,"Otwieram gniazdo nasłuchujące\n");
#endif

   wyjscie=stworzGniazdoNasluchujace(&gniazdo);
   if(wyjscie==-1)
   {
      return -1;
   }
   wyjscie=stworzGniazdoNasluchujaceIPv6(&gniazdoIPv6);
   if(wyjscie==-1)
   {
      return -1;
   }

   piszsyslog("Inicjalizuję centralę",false);
#ifdef DEBUG
   /*Sprawdziłem, na tym etapie jest poprawnie otworzone gniazdo*/
   /*
   struct sockaddr_storage adres;
   uint8_t bufor[MAX_PAKIET];
   odbierzpakiet(gniazdo,&adres,bufor);
   */
   fprintf(stderr,"Inicjalizuję centralę\n");
#endif
   wyjscie=inicjalizujCentrale(gniazdo);
   if(wyjscie==-1)
   {
      return -1;
   }

   wyjscie=inicjalizujCentraleIPv6(gniazdoIPv6);
   if(wyjscie==-1)
   {
      return -1;
   }

    piszsyslog("Wchodzę do głównej pętli",false);
#ifdef DEBUG
   wypiszKomunikatory();
   fprintf(stderr,"Wchodzę do głównej pętli\n");
#endif
petlaglowna:
    piszsyslog("Zaraz poczekam na komunikaty",false);
#ifdef DEBUG
   fprintf(stderr,"Zaraz poczekam na komunikaty\n");
#endif
   wyjscie=oczekujNaKomunikaty(&k,&kIPv6,&ilosc,&iloscIPv6);
   if(wyjscie==-1)
   {
      return -1;
   }
#ifdef DEBUG
   fprintf(stderr,"Lista komunikatorów po oczekiwaniu\n");
   wypiszKomunikatory();
   fprintf(stderr,"Coś czeka\n");
#endif
   for(i=0;i<ilosc;++i)
   {

#ifdef DEBUG
   fprintf(stderr,"Przetwarzam\n");
#endif
      wyjscie=pobierzWyslij(k[i]);
      if(wyjscie==-1)
      {
	 return -1;
      }
   }
   for(i=0;i<iloscIPv6;++i)
   {

#ifdef DEBUG
   fprintf(stderr,"Przetwarzam\n");
#endif
      wyjscie=pobierzWyslijIPv6(kIPv6[i]);
      if(wyjscie==-1)
      {
	 return -1;
      }
   }

piszsyslog("Komunikaty przetworzone",false);
#ifdef DEBUG
   fprintf(stderr,"Pobrałem i wysłałem\n");
#endif
   goto petlaglowna;

   return EXIT_SUCCESS;
}
   /*
    * -1. Otwórz gniazdo nasłuchujące
    * 2. Zaakceptuj połączenie i utwórz nowy wątek
    * 3. Czekaj na polecenia
    * 4. Jeśli dostaniesz SET to ustaw parametry transmisji
    * 5. Jeśli dostaniesz LIST wyślij listę plików
    * 6. Jeśli dostaniesz QUIT zamknij połączenie
    * 7. Jeśli dostaniesz GET nazwa_pliku zwróć numer portu
    * 8. Prześlij plik
    */

